using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Watchfire.AppScan;
using Watchfire.AppScan.Extensions;
using Watchfire.AppScan.Scan.Data;
using System.Threading;

namespace Watchfire.DefectLogger
{

    public abstract class DefectLoggerPluginBase
	{
		#region Members
		private IAppScan _appScan = null;
		private DefectSystemConfig _defectSystemConfig = new DefectSystemConfig();
		#endregion

		#region Properties

		public DefectSystemConfig Config
		{
			get { return _defectSystemConfig; }
		}

		public abstract IDefectTrackingSystem DefectTrackingSystem
		{
			get;
		}
		protected abstract string RegDefectLoggerPlugin
		{
			get;
		}
		protected abstract string RegXmlConfig
		{
			get;
		}
		protected abstract ConnectionForm ConnForm
		{
			get;
		}

		protected abstract string ContextMenuText
		{
			get;
		}

		protected abstract string PluginMenuText
		{
			get;
		}

		#endregion


		/// <summary>
		/// CTor
		/// </summary>
		/// <param name="regKeyName">shortname for registry key for plugin registry storage</param>
		/// <param name="regValueName">name for string value</param>
		public DefectLoggerPluginBase()
		{
        }

        #region IExtensionLogic Members

        /// <summary>
        /// extension initialization. typically called on AppScan's startup
        /// </summary>
        /// <param name="appScan">main application object the extension is loaded into</param>
        /// <param name="extensionDir">extension's working directory</param>
        public void Load(IAppScan appscan, IAppScanGui appScanGui, string extensionDir)
        {
            /*
             * perform actions required for the extension to start running.
             * this is the place to register to AppScan events and GUI hooks.
             * for example:
             
                appScan.Scan.Exploring += MyExt.OnExploringEvent;
             
             */

            // Store the AppScan Instance
            _appScan = appscan;

            // Load the config from the registry, if it exists there
            string storedConfig = PluginRegistry.Read(_appScan.RegistryPath, RegDefectLoggerPlugin, RegXmlConfig);
            if (storedConfig != null && storedConfig.Length > 0)
            {
                _defectSystemConfig = DefectSystemConfig.FromXml(storedConfig);
            }

            //RegisterToEvents(_appScan);
            //Scan Scan.<IssuesEventArgs

            //ReadSettings();

            appScanGui.ExtensionsMenu.Add(new MenuItem<EventArgs>(PluginMenuText, ThreadConnForm));
            appScanGui.IssueContextMenu.Add(new MenuItem<IssuesEventArgs>(ContextMenuText, LogIssue));
            //appScanGui.
        }

        private void StartNewStaThreadConnForm() { 
            Application.Run(new DefectSystemConfigForm(ConnForm, this));
	    }

	    /// <summary>
	    /// Shows the main dialog of this extension
	    /// </summary>
	    /// <param name="e">event args</param>
	    public void ThreadConnForm(EventArgs e)
	    {
            // Our Forms require Single Thread Appartment State.
            Thread t = new Thread(new ThreadStart(StartNewStaThreadConnForm));
            t.SetApartmentState(ApartmentState.STA);
            t.Start();
	    }

        /// <summary>
        /// Shows the dialog logging a new issue
        /// </summary>
        /// <param name="e">event args</param>
        public void ThreadLogIssue(IssuesEventArgs e)
        {
            ThreadStart starter = delegate { LogIssue(e); };
            Thread t = new Thread(starter);
            t.SetApartmentState(ApartmentState.STA);
            t.Start();
        }        

        /// <summary>
        /// retrieves data about current available ext-version
        /// </summary>
        /// <param name="targetApp">app this extension is designated for</param>
        /// <param name="targetAppVersion">current version of targetApp</param>
        /// <returns>update data of most recent extension version, or null if no data was found, or feature isn't supported. it is valid to return update data of current version. extension-update will take place only if returned value indicaes a newer version</returns>
        public ExtensionVersionInfo GetUpdateData(Edition targetApp, System.Version targetAppVersion)
        {
            return null;
        }

        #endregion

        /// <summary>
        /// Returns a formatted name for the issue entity
        /// </summary>
        /// <param name="entity">the entity</param>
        /// <returns>formatted string</returns>
		public static string GetEntityDesc(IEntity entity)
		{
			if (entity.Type == EntityType.Page)
				return entity.Url.Path;
			else
				return entity.Url.Path + " (" + entity.Type.ToString() + " " + entity.Name + ")";
		}

        public void LogIssue(IssuesEventArgs e)
		{
            try
            {
                foreach(IIssue issue in e.issues){
                    //Only need the first one selected, should only be 1 in the collection.
                    LogDefectForm def = new LogDefectForm(this, issue, 0, 0);
                    
                    def.SetDesktopLocation(Screen.PrimaryScreen.Bounds.Width / 3 - def.Width / 2, Screen.PrimaryScreen.Bounds.Height / 3 - def.Height / 2);
                    def.ShowDialog();
                    break;
                }
            }
            catch (Exception ex)
            {
				//_appScan.Debug.Logger.Log(ex.ToString());
            }
		}

		public void SaveConfig(DefectSystemConfig config)
		{
			// Keep the config in a member
			_defectSystemConfig = config;

			// Store it in the registry as one XML blob
			PluginRegistry.WriteSettings(_appScan.RegistryPath, RegDefectLoggerPlugin, RegXmlConfig, _defectSystemConfig.ToXml());
		}

    }
}
